/*
 * @Description: 自己封装一个fetch请求库
 * @Author: 呆龙
 * @Date: 2023-09-17 20:54:07
 * @LastEditTime: 2023-09-20 15:01:23
 * @LastEditors: 呆龙
 */
// method: "POST", // *GET, POST, PUT, DELETE, etc.
// mode: "cors", // no-cors, *cors, same-origin
// cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
// credentials: "same-origin", // include, *same-origin, omit
// headers: {
//   "Content-Type": "application/json",
//   // 'Content-Type': 'application/x-www-form-urlencoded',
// },
// redirect: "follow", // manual, *follow, error
// referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
// body: JSON.stringify(data), // body data type must match "Content-Type" header
import qs from "qs";

interface RequestInit {
  /** A BodyInit object or null to set request's body. */
  body?: BodyInit | null;
  /** A string indicating how the request will interact with the browser's cache to set request's cache. */
  cache?: RequestCache;
  /** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */
  credentials?: RequestCredentials;
  /** A Headers object, an object literal, or an array of two-item arrays to set request's headers. */
  headers?: HeadersInit;
  /** A cryptographic hash of the resource to be fetched by request. Sets request's integrity. */
  integrity?: string;
  // /** A boolean to set request's keepalive. */
  // keepalive?: boolean;
  /** A string to set request's method. */
  method?: string;
  /** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */
  mode?: RequestMode;
  /** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */
  redirect?: RequestRedirect;
  /** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */
  referrer?: string;
  /** A referrer policy to set request's referrerPolicy. */
  referrerPolicy?: ReferrerPolicy;
  /** An AbortSignal to set request's signal. */
  signal?: AbortSignal | null;
  /** parmes */
  params?: null | object;
  /** url */
  url?: string;
  /** baseUrl */
}
// 默认导入http
export const http: any = function (config: RequestInit) {
  config = {
    method: "GET",
    mode: "cors",
    cache: "no-cache",
    credentials: "same-origin",
    headers: {
      "Content-Type": "application/json",
    },
    redirect: "follow",
    referrerPolicy: "no-referrer",
    ...config,
  };

  let {
    method,
    headers,
    params,
    url,
    body,
    mode,
    cache,
    credentials,
    redirect,
    referrerPolicy,
  } = config;
  // 需要处理和校验参数在这里处理
  // 处理params参数
  if (params && typeof params === "object" && params !== null) {
    const paramsStr = qs.stringify(params);
    url += url!.includes("?") ? `&${paramsStr}` : `?${paramsStr}`;
  }
  // 处理body参数
  headers = new Headers();
  if (body && typeof body === "object" && body !== null) {
    body = JSON.stringify(body);
    headers.append("Content-Type", "application/json");
  }
  /** 请求拦截器  在此可以获取token保存等。。。。 */
  headers.append(
    "X-Access-Token",
    "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDA1NTU0MDgsInVzZXJuYW1lIjoidGhpbmtzb2Z0In0.BVDjQGgkFGmciLKA_aN33vkx57qAqHLUuOxl84bmhCo"
  );


  /**  */
  /** 最后的配置项合并 */
  config = {
    method: method?.toUpperCase(),
    mode,
    cache,
    headers,
    credentials,
    redirect,
    referrerPolicy,
  };
  if (/^(POST|PUT|PATCH)$/.test(method!)) {
    config["body"] = body;
  }
  console.log(url);

  return fetch(url!, config)
    .then(response => {
      const { status, statusText } = response;
      if (/^(2|3)\d{2}$/.test(status + "")) {
        return response.json();
      }

      return Promise.reject({
        code: -100,
        status,
        statusText,
      });
    })
    .catch(reason => {
      /** 此处可以定义失败的统一提示 */
      console.log(reason);
      return Promise.reject(reason);
    });
};

const firstHttp = ["GET", "DELETE", "OPTIONS", "HEAD"];
firstHttp.forEach(item => {
  http[item.toLowerCase()] = (
    url: string,
    params?: null | object,
    config: RequestInit = {}
  ) => {
    config!["method"] = item.toLowerCase();
    config!["params"] = params;
    config!["url"] = url;
    return http(config);
  };
});
const secondHttp = ["POST", "PUT", "PATCH"];
secondHttp.forEach(item => {
  http[item.toLowerCase()] = (
    url: string,
    body?: BodyInit | null,
    config: RequestInit = {}
  ) => {
    config!["method"] = item;
    config!["body"] = body;
    config!["url"] = url;
    return http(config);
  };
});
